#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
用户操作日志模块
用于记录用户登录、注销和操作行为
"""

import logging
import time
import json
import functools
import traceback
from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed
from django.dispatch import receiver
from django.http import HttpRequest

# 获取用户操作日志记录器
user_logger = logging.getLogger('user')


@receiver(user_logged_in)
def log_user_login(sender, request, user, **kwargs):
    """
    记录用户登录事件
    """
    ip = get_client_ip(request)
    user_agent = request.META.get('HTTP_USER_AGENT', '')
    user_logger.info(f"User Login: {user.username} (ID:{user.id}) from IP:{ip} Agent:{user_agent}")


@receiver(user_logged_out)
def log_user_logout(sender, request, user, **kwargs):
    """
    记录用户注销事件
    """
    if user:
        ip = get_client_ip(request)
        user_logger.info(f"User Logout: {user.username} (ID:{user.id}) from IP:{ip}")


@receiver(user_login_failed)
def log_user_login_failed(sender, credentials, request, **kwargs):
    """
    记录登录失败事件
    """
    # 获取尝试登录的用户名，但不记录密码
    username = credentials.get('username', '<unknown>')
    ip = get_client_ip(request) if request else 'N/A'
    user_agent = request.META.get('HTTP_USER_AGENT', '') if request else 'N/A'
    user_logger.warning(f"Login Failed: username={username} from IP:{ip} Agent:{user_agent}")


def get_client_ip(request):
    """
    获取客户端IP地址
    """
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0].strip()
    else:
        ip = request.META.get('REMOTE_ADDR', '')
    return ip


def log_user_action(action_type):
    """
    用户操作日志装饰器
    
    参数:
        action_type: 操作类型描述，如 'View Profile', 'Edit Settings', 等
    
    用法:
        @log_user_action('Edit Profile')
        def profile_edit_view(request):
            ...
    """
    def decorator(view_func):
        @functools.wraps(view_func)
        def wrapper(request, *args, **kwargs):
            start_time = time.time()
            
            # 获取用户信息
            user = request.user
            user_id = user.id if user.is_authenticated else None
            username = user.username if user.is_authenticated else 'Anonymous'
            ip = get_client_ip(request)
            
            # 记录操作开始信息
            user_logger.info(f"Action Start: {action_type} by {username} (ID:{user_id}) from IP:{ip}")
            
            try:
                # 执行原视图函数
                response = view_func(request, *args, **kwargs)
                
                # 计算处理时间
                duration = time.time() - start_time
                
                # 记录操作完成信息
                status_code = getattr(response, 'status_code', 0)
                user_logger.info(f"Action Complete: {action_type} by {username} (ID:{user_id}) - Status:{status_code} in {duration:.2f}s")
                
                return response
                
            except Exception as e:
                # 记录操作异常信息
                user_logger.error(f"Action Error: {action_type} by {username} (ID:{user_id}) - {str(e)}")
                user_logger.error(traceback.format_exc())
                raise
        
        return wrapper
    
    return decorator


class UserActivityMiddleware:
    """
    用户活动中间件，跟踪用户会话活动
    """
    
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        # 在处理请求前执行的代码
        
        # 获取用户和会话信息
        user = getattr(request, 'user', None)
        session_key = request.session.session_key if hasattr(request, 'session') else None
        
        # 记录用户活动
        if user and user.is_authenticated and not request.path.startswith('/static/') and not request.path.startswith('/media/'):
            ip = get_client_ip(request)
            path = request.path
            method = request.method
            
            if not path.startswith('/admin/jsi18n/') and not path.endswith('.js') and not path.endswith('.css'):
                user_logger.debug(f"User Activity: {user.username} (ID:{user.id}) - {method} {path} from IP:{ip}")
        
        # 继续处理请求
        response = self.get_response(request)
        
        # 在视图处理后执行的代码
        
        return response 